package com.doublefish.doublefishrobot.ui.home.path.tools;

import com.doublefish.doublefishrobot.ui.home.path.bean.VelocityBean;

import java.util.ArrayList;
import java.util.List;

/**
 * 作者:dugaofeng on 2025/4/9 16:09
 */
public class PingPongUtils {

    //重力加速度 默认9.8
    private static float g = 9.8f;
    //乒乓球的重量  默认 2.5g
    private static float m = 0.0025f;
    //空气阻力系数 默认0.5
    private static float coefficientOfAirdrag = 0.5f;
    //空气密度 默认1.293 kg/m³
    private static float ρ = 1.293f;


    /// 发球机的球的落点、轨迹
    /// - Parameters:
    ///   - height: 发球机口距离台面的高度
    ///   - velocity: 初始速率
    ///   - angularVelocity: 旋转的角速度
    ///   - sideSpin: 侧旋的角度
    public static List<float[]> martix(float height, VelocityBean velocity, float angularVelocity, float sideSpin) {
        PathBean path = new PathBean();

        List<float[]> matrix = new ArrayList();
        // 每次0.001秒
        float dt = 0.001f;

        int index = 0;
        while (-path.sz < height) {
            //空气阻力
            float airDrag = airDrag(velocity.getSpeed());
            //空气阻力的方向始终与速率的方向相反 (计算空气阻力的xyz的分量)
            float airDragX = -airDrag * velocity.getVx() / velocity.getSpeed();
            float airDragY = -airDrag * velocity.getVy() / velocity.getSpeed();
            float airDragZ = -airDrag * velocity.getVz() / velocity.getSpeed();

            //马格努斯效应
            float magnus = calMagnus(velocity.getSpeed(), angularVelocity);
            float magnusX = (float) (Math.sin(sideSpin) * magnus * Math.sqrt((velocity.getVy() * velocity.getVy() + velocity.getVz() * velocity.getVz()) / velocity.getSumOfSquares()));
            float magnusY = (float) (magnus * Math.sqrt((velocity.getVx() * velocity.getVx() + velocity.getVz() * velocity.getVz()) / velocity.getSumOfSquares()));
            float magnusZ = (float) (Math.cos(sideSpin) * magnus * Math.sqrt((velocity.getVy() * velocity.getVy() + velocity.getVx() * velocity.getVx()) / velocity.getSumOfSquares()));
            if (velocity.getVz() >= 0) {
                magnusY = - magnusY;
            }

            //计算各个方向的加速度
            // 空气阻力 马格努斯效应 重力加速度
            float ax = ((airDragX + magnusX) / m);
            float ay = ((airDragY + magnusY)/ m);
            float az = ((airDragZ + magnusZ) / m - g);

            //计算各个方向的移动距离
            path.sx += velocity.getVx() * dt + 0.5 * ax * dt * dt;
            path.sy += velocity.getVy() * dt + 0.5 * ay * dt * dt;
            path.sz += velocity.getVz() * dt + 0.5 * az * dt * dt;

            velocity.setVx(velocity.getVx() + ax * dt);
            velocity.setVy(velocity.getVy() + ay * dt);
            velocity.setVz(velocity.getVz() + az * dt);

            float[] point = {path.sx, path.sy, path.sz};
            matrix.add(point);

            index++;
        }

        return matrix;
    }


//region - 空气阻力

//空气阻力公式，可计算出空气阻力：
//f=1/2ρ*C_d*S*V*V
//
//
//其中，f为空气阻力，ρ为空气密度，C_d为空气阻力系数，A为乒乓球的迎风面积，v为乒乓球的速度
//根据已知条件，我们可以得出：
//ρ = 1.178 kg/m³ 百度查到的空气密度 标准条件下（0℃，1个标准大气压（1atm）），空气密度约为1.29kg/m³。温度25摄氏度，相对湿度40%，此时空气密度为1.178kg/m³
//C_d = 0.5       百度查到的空气阻力系数，默认0.5
//S = 0.001256 m²   乒乓球直径40mm 半径20mm， 迎风面当做圆计算 面积=3.14*0.02^2
//v = 30 m/s      乒乓球初始速度假设为30m/s 根基实际测试超6的乒乓球速度能达到30m/s
//
// 阻力f: 1.293 * 0.5 * 0.001256 * 30 * 30
// 乒乓球重量大约 m=2.5g = 0.0025kg
// 乒乓球的阻力产生的加速度 f/m =  0.09616250000000001

    /// 计算空气阻力
    /// - Parameter speed: 当前乒乓球的速度
    private static float airDrag(float speed) {
        return 0.5f * 0.5f * ρ * 0.001256f * speed * speed;
    }

    /// 空气阻力造成的加速度
    /// - Parameter speed: 当前乒乓球的速度
    private static float accelerationOfAirdrag(float speed) {
        float ad = airDrag(speed);
        return ad / m;
    }


    /// 根据牛顿第二定律，计算自由落体的时间
    /// s=2gt^2 t = sqr(s/2g)
    /// 如果speedV不为0, t0 = v/g; t = sqr(t0*t0 + s/(2g))
    /// t上=t+t0  t下=t-t0
    /// - Parameters:
    ///   - height: 高度
    ///   - speed: 垂直方向的速度
    ///   - isUp: 如果有初始速度，方向是否是向上， 0 NO.下   1 YES.上
    private static float getTime(float height, float speed, boolean isUp) {
        if (PingPongTools.isZero(speed)) {
            // 假设发球口高0.3 根据是 s=2gt^2;
            // t = 0.1237179148263484
            return (float) Math.sqrt(0.5 * height / g);
        }
        float t0 = speed / g;
        float t = (float) Math.sqrt(t0 * t0 + 0.5 * height / g);
        return isUp ? (t + t0) : (t - t0);
    }

//endregion

    //region - 马格努斯效应

    /// 计算马格努斯效应产生的力
    /// 公式 L = 4/3(4*M_PI^2*b^3*s*ρ*V)
    /// 其中 ρ表示空气密度 b表示乒乓球半径 s表示旋转的角速度 V表示速度
    /// - Parameters:
    ///   - speed: 速度
    ///   - angularVelocity: 角速度 （如果是上旋球，角速度为正 ， 否则为负）
    private static float calMagnus(float speed, float angularVelocity) {
        if (PingPongTools.isZero(speed) || PingPongTools.isZero(angularVelocity)) {
            return 0;
        }
        float r = 0.02f;  //v40+球的半径是20mm
        //上旋球 马格努斯力 向下   下旋时，马格努斯力 向上
        return (float) -(4 * Math.PI * Math.PI * r * r * r * angularVelocity * speed * ρ) * 4 / 3;
    }

//endregion

    //内部类
    static class PathBean {
        private float sx;   //x轴的移动距离
        private float sy;   //y轴的移动距离
        private float sz;   //z轴的移动距离

        public float getSx() {
            return sx;
        }

        public void setSx(float sx) {
            this.sx = sx;
        }

        public float getSy() {
            return sy;
        }

        public void setSy(float sy) {
            this.sy = sy;
        }

        public float getSz() {
            return sz;
        }

        public void setSz(float sz) {
            this.sz = sz;
        }
    }
}
